package com.zhidao.backend.service.Impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.zhidao.backend.common.*;
import com.zhidao.backend.entity.User;
import com.zhidao.backend.exception.BusinessException;
import com.zhidao.backend.mapper.UserMapper;
import com.zhidao.backend.service.IUserService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户服务实现
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Value("${spring.mail.username}")
    private String from;
    @Resource
    private JavaMailSender mailSender;

    @Override
    public void sendBanMail(String to) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);
        message.setSubject("知道平台，账号封禁");
        message.setText("近期因为您的行为，系统评定您的账号出现违规行为，30天后请联系本邮箱删除");
        mailSender.send(message);
    }
    @Override
    public void register(@NotNull RegisterRequest registerRequest) {
        boolean userExist = baseMapper.exists(new QueryWrapper<User>().eq("username", registerRequest.getUsername()));
        if (userExist) {
            throw new BusinessException(StatusCode.PARAM_ERROR.getCode(), "用户名已存在");
        }
        Date date = new Date();
        Timestamp timestamp = new Timestamp(date.getTime());
        String encryptedPassword = DigestUtils.md5DigestAsHex(registerRequest.getPassword().getBytes(StandardCharsets.UTF_8));
        User user = new User();
        user.setUsername(registerRequest.getUsername());
        user.setPassword(encryptedPassword);
        user.setCreatedDate(timestamp);
        user.setEmail(registerRequest.getEmail());
        user.setEducation(registerRequest.getEducation());
        user.setDescription("");
        user.setDays(0);
        user.setScore(0);
        user.setRoutes(0);
        user.setLearn(0);
        user.setSubscribe(0);
        user.setCollect(0);
        user.setFollowers(0);
        List<String> tags = new ArrayList<>();
        String tagsJson = new Gson().toJson(tags);
        user.setTagStr(tagsJson);
        user.setVip(false);
        user.setDeleted(false);
        user.setAdmin(false);
        user.setBanned(false);
        int num = baseMapper.insert(user);
        if (num < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "注册失败，请重试");
        }
    }

    @Override
    public User login(@NotNull LoginRequest loginRequest) {
        User user = baseMapper.selectOne(new QueryWrapper<User>().eq("email", loginRequest.getEmail()));
        if (user == null) {
            throw new BusinessException(StatusCode.PARAM_ERROR.getCode(), "用户不存在");
        }
        String encryptedPassword = DigestUtils.md5DigestAsHex(loginRequest.getPassword().getBytes(StandardCharsets.UTF_8));
        if (!user.getPassword().equals(encryptedPassword)) {
            throw new BusinessException(StatusCode.PARAM_ERROR.getCode(), "密码错误");
        }
        if (user.getBanned()) {
            throw new BusinessException(StatusCode.PARAM_ERROR.getCode(), "用户已被封禁");
        }
        user.setTags(new Gson().fromJson(user.getTagStr(), new TypeToken<List<String>>() {
        }.getType()));
        user.setPassword(null);//脱敏;
        return user;
    }

    @Override
    public void delete(Long id) {
        int res = baseMapper.deleteById(id);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "注销失败");
        }
    }

    @Override
    public String getUsernameById(Long id) {
        return baseMapper.selectById(id).getUsername();
    }

    @Override
    public User getUserInfo(Long id) {
        User user = baseMapper.selectById(id);
        if (user == null) {
            throw new BusinessException(StatusCode.PARAM_ERROR.getCode(), "用户不存在");
        }
        user.setPassword(null);
        user.setTags(new Gson().fromJson(user.getTagStr(), new TypeToken<List<String>>() {
        }.getType()));
        return user;
    }



    @Override
    public void updateProfile(@NotNull UpdateRequest updateRequest) {
        for (String column : updateRequest.getUpdateAttribute().keySet()) {
            if (column.equals("tags")) {
                Object tags = updateRequest.getUpdateAttribute().get(column);
                String tagsJson = new Gson().toJson(tags);
                UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("id", updateRequest.getId()).set("tags", tagsJson);
                int res = baseMapper.update(null, updateWrapper);
                if (res < 1) {
                    throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "更新失败");
                }
            } else {
                UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("id", updateRequest.getId()).set(column, updateRequest.getUpdateAttribute().get(column));
                int res = baseMapper.update(null, updateWrapper);
                if (res < 1) {
                    throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "更新失败");
                }
            }
        }
    }

    @Override
    public void updateAvatar(Long id, String url) {
        int res = baseMapper.update(null, new UpdateWrapper<User>().eq("id", id).set("avatar", url));
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "头像上传失败，请重试");
        }
    }

    @Override
    public void existUser(Long id) {
        User user = baseMapper.selectById(id);
        if (user == null) {
            throw new BusinessException(StatusCode.PARAM_ERROR.getCode(), "用户不存在");
        }
    }

    @Override
    public void follow(Long id) {
        User user = baseMapper.selectById(id);
        user.setSubscribe(user.getSubscribe() + 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "关注失败，请重试");
        }
    }

    @Override
    public void beFollowed(Long id) {
        User user = baseMapper.selectById(id);
        user.setFollowers(user.getFollowers() + 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "关注失败，请重试");
        }
    }

    @Override
    public List<User> search(String keyword) {
        Wrapper<User> queryWrapper = new QueryWrapper<>();
        List<User> userList = baseMapper.selectList(queryWrapper);
        Gson gson = new Gson();
        return userList.stream().filter(user -> {
            String tagStr = user.getTagStr();
            Set<String> tags = gson.fromJson(tagStr, new TypeToken<Set<String>>(){}.getType());
            return user.getUsername().contains(keyword) || user.getDescription().contains(keyword) || tags.contains(keyword);
        }).peek(user -> user.setPassword(null)).collect(Collectors.toList());
    }

    @Override
    public void signIn(Long id) {
        User user = baseMapper.selectById(id);
        user.setDays(user.getDays() + 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "签到失败，请重试");
        }
    }

    @Override
    public void likeRoute(Long id) {
        User user = baseMapper.selectById(id);
        user.setRoutes(user.getRoutes() + 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "点赞失败，请重试");
        }
    }

    @Override
    public void collectRoute(Long id) {
        User user = baseMapper.selectById(id);
        user.setCollect(user.getCollect() + 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "收藏失败，请重试");
        }
    }

    @Override
    public void cancelCollectRoute(Long id) {
        User user = baseMapper.selectById(id);
        user.setCollect(user.getCollect() - 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "取消收藏失败，请重试");
        }
    }

    @Override
    public void unlikeRoute(Long userId) {
        User user = baseMapper.selectById(userId);
        user.setRoutes(user.getRoutes() - 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "取消点赞失败，请重试");
        }
    }

    @Override
    public void learnRoute(Long userId) {
        User user = baseMapper.selectById(userId);
        user.setLearn(user.getLearn() + 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "学习失败，请重试");
        }
    }

    @Override
    public void cancelLearnRoute(Long userId) {
        User user = baseMapper.selectById(userId);
        user.setLearn(user.getLearn() - 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "取消学习失败，请重试");
        }
    }

    @Override
    public void giveAdmin(Long userId){
        User user = baseMapper.selectById(userId);
        user.setAdmin(true);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "给予管理员权限失败，请重试");
        }
    }

    @Override
    public Boolean isAdministrator(Long userId){
        User user = baseMapper.selectById(userId);
        return user.getAdmin();
    }
    @Override
    public void banUser(@NotNull BanUserRequest banUserRequest) {
        User banner = baseMapper.selectById(banUserRequest.getBanner());
        User Receiver = baseMapper.selectById(banUserRequest.getReceiver());
        if(!banner.getAdmin()) {
            throw new BusinessException(StatusCode.REJECT.getCode(), "没有管理员权限！");
        }
        Receiver.setBanned(true);
        Runnable send = () -> sendBanMail(Receiver.getEmail());
        new Thread(send).start();
        baseMapper.updateById(Receiver);
    }
    @Override
    public void unsealUser(@NotNull UnsealRequest unsealRequest){
        User banner = baseMapper.selectById(unsealRequest.getAdminId());
        User Receiver = baseMapper.selectById(unsealRequest.getUser());
        if(!banner.getAdmin()) {
            throw new BusinessException(StatusCode.REJECT.getCode(), "没有管理员权限！");
        }
        Receiver.setBanned(false);
        baseMapper.updateById(Receiver);
    }

    @Override
    public void changePassword(ChangePasswordRequest changePasswordRequest) {
        User user = baseMapper.selectById(changePasswordRequest.getId());
        String encryptedPassword = DigestUtils.md5DigestAsHex(changePasswordRequest.getOldPassword().getBytes(StandardCharsets.UTF_8));
        if (!user.getPassword().equals(encryptedPassword)) {
            throw new BusinessException(StatusCode.PARAM_ERROR.getCode(), "旧密码错误");
        }
        user.setPassword(DigestUtils.md5DigestAsHex(changePasswordRequest.getNewPassword().getBytes(StandardCharsets.UTF_8)));
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "修改密码失败，请重试");
        }
    }

    @Override
    public void unfollow(Long followerId) {
        User user = baseMapper.selectById(followerId);
        user.setSubscribe(user.getSubscribe() - 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "取消关注失败，请重试");
        }
    }

    @Override
    public void beUnfollowed(Long bloggerId) {
        User user = baseMapper.selectById(bloggerId);
        user.setFollowers(user.getFollowers() - 1);
        int res = baseMapper.updateById(user);
        if (res < 1) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR.getCode(), "被取消关注失败，请重试");
        }
    }

    @Override
    public void isBanned(Long userId) {
        User user = baseMapper.selectById(userId);
        if(user.getBanned()){
            throw new BusinessException(StatusCode.BANNED.getCode(), "用户已被封禁！");
        }
    }

}
